<template>
  <div>
    <!-- 搜索条件 -->
    <el-card v-show="showQueryForm" class="form-card">
      <QueryForm ref="queryFormRef" :form-data="queryFormData" :items="queryFormItems" :model="queryFormData" :show-control="true" label-width="82px">
        <!--        <QueryFormItem v-if="tabActive === 0" label="商品状态" prop="status">
                  <DictSelect v-model="queryFormData.status" dict-type="shop_goods_status" placeholder="请选择商品状态"/>
                </QueryFormItem>-->

        <QueryFormItem label="商品标签">
          <MultipleSelect v-model="markFlagList" :options="markFlagOptions" placeholder="请选择商品标签"/>
        </QueryFormItem>

        <QueryFormItem label="归属店铺" prop="shop_id">
          <el-select v-model="queryFormData.shop_id" clearable placeholder="请选择供归属店铺">
            <el-option v-for="item in shopList" :key="item.id" :label="'[' + item.id + '] ' + item.name" :value="item.id"/>
          </el-select>
        </QueryFormItem>

        <QueryFormItem label="商品分类" prop="cate_id">
          <TreeSelect ref="cateTreeRef" v-model="cateName" :tree-data="cateTreeData" @selectChange="handleSelectCate"/>
        </QueryFormItem>

        <QueryFormItem label="创建时间">
          <el-date-picker v-model="pickerDate"
                          :shortcuts="pickerShortcuts"
                          class="card-header-extra-action"
                          clearable
                          end-placeholder="结束日期"
                          format="YYYY-MM-DD"
                          start-placeholder="开始日期"
                          type="daterange"
                          value-format="YYYY-MM-DD"/>
        </QueryFormItem>

        <template #control>
          <el-button icon="Search" type="info" @click="handleSearch">{{ $t('form.search') }}</el-button>
          <el-button icon="Refresh" @click="handleResetQuery">{{ $t('form.reset') }}</el-button>
        </template>
      </QueryForm>
    </el-card>

    <!-- 列表数据 -->
    <el-card class="content-card">
      <el-tabs v-model="tabActive" @tab-change="handleTabChange">
        <el-tab-pane v-for="item in tabHeaderList" :key="item.type" :label="`${item.name}(${item.count})`" :name="item.type"></el-tab-pane>
      </el-tabs>

      <!-- 工具栏 -->
      <table-toolbar v-model:columns="columns"
                     v-model:show-query-form="showQueryForm"
                     v-model:size="size"
                     v-model:stripe="stripe"
                     @refresh="handleSearch">
        <!-- 操作区域 -->
        <el-button v-permission="'shop:goods:create'" icon="circle-plus" plain type="primary" @click="handleFormShow(null, 1)">新增</el-button>
        <el-button v-permission="'shop:goods:batch_update'" icon="edit-pen" plain type="primary" @click="handleShowBatchModify">批量修改</el-button>
        <el-button v-permission="'shop:goods:excel'" icon="promotion" plain type="warning" @click="handleDownloadExport">导出数据</el-button>
      </table-toolbar>

      <!-- 列表记录 -->
      <div class="table-wrapper">
        <!-- 列表数据 -->
        <el-table ref="tableRef"
                  v-loading="loading"
                  :data="tableData"
                  :size="size"
                  :stripe="stripe"
                  row-key="id"
                  show-overflow-tooltip
                  @select="handleSelectChange"
                  @select-all="handleSelectAll"
                  @sort-change="handleSortChange">
          <template #empty>
            <el-empty class="table-empty" description="暂无数据"/>
          </template>

          <table-column :columns="columns">
            <template #cover_url="scope">
              <div class="sku-info-box">
                <el-image :preview-src-list="[scope.row.cover_url]" :preview-teleported="true" :src="scope.row.cover_url" fit="cover" lazy/>
              </div>
            </template>

            <template #name="scope">
              <div class="sku-info-box">
                <div class="sku-info-right">
                  <div class="sku-name">{{ scope.row.name }}</div>
                </div>
              </div>
            </template>

            <template #type="scope">
              <DictTag v-model="scope.row.type" :circle="false" dict-type="shop_goods_type"/>
            </template>

            <template #status="scope">
              <DictTag v-model="scope.row.status" :circle="false" dict-type="shop_goods_status"/>
            </template>

            <template #mark_flag="scope">
              <MultipleTag :flag-val="scope.row.mark_flag" :options="markFlagOptions" class="mark_flag" default-name=""/>
            </template>

            <template #sales_count="scope">
              <div @click="handleUpdateSalesCount(scope.row)">
                <span>{{ scope.row.sales_count || '-' }}</span>
              </div>
            </template>

            <template #order_num="scope">
              <div @click="handleUpdateOrderNum(scope.row)">
                <span>{{ scope.row.order_num || '-' }}</span>
              </div>
            </template>

            <template #operations="scope">
              <el-button v-permission="'shop:goods:info'" link type="info" @click="handleFormShow(scope.row, 0)">查看</el-button>
              <el-button v-if="hasPermission('shop:goods:update') && (scope.row.status !== 100 && scope.row.status !== 120)" link type="primary" @click="handleFormShow(scope.row, 2)">编辑</el-button>
              <el-button v-if="hasPermission('shop:goods:update')" link type="primary" @click="showGoodsStoreForm(scope.row.id)">库存</el-button>

              <div style="margin-top: 5px">
                <template v-if="hasPermission('shop:goods:audit')">
                  <!-- 商品状态 0:草稿 10:审核中 50:审核失败 90:待上架 100:已上架 110:已下架 120:已删除 -->
                  <el-button v-if="[0,10,50].includes(scope.row.status)" link type="success" @click="handleFormShow(scope.row, 3)">审核</el-button>

                  <!-- 上下架操作 -->
                  <el-button v-if="scope.row.status === 100" link type="warning" @click="handleUpdateSaleStatus(scope.row, false)">下架</el-button>
                  <el-button v-if="scope.row.status === 90 || scope.row.status === 110" link type="success" @click="handleUpdateSaleStatus(scope.row, true)">上架</el-button>
                </template>

                <!-- 删除操作 -->
                <template v-if="hasPermission('shop:goods:delete')">
                  <el-button v-if="scope.row.status !== 100 && scope.row.status !== 120" link type="danger" @click="handleGoodsDelete(scope.row)">删除</el-button>
                  <el-button v-if="scope.row.status === 120" link type="danger" @click="handleGoodsRestore(scope.row)">恢复</el-button>
                </template>
              </div>
            </template>
          </table-column>
        </el-table>

        <!-- 分页操作 -->
        <el-pagination v-if="totalCount > 0"
                       :current-page="pageQuery.pageNum"
                       :page-size="pageQuery.pageSize"
                       :page-sizes="pageSizes"
                       :total="totalCount"
                       background
                       class="table-pagination"
                       layout="total, sizes, prev, pager, next"
                       @size-change="handleSizeChange"
                       @current-change="handleCurrentChange"/>
      </div>
    </el-card>

    <!-- 批量修改操作 -->
    <GoodsBatchModify ref="batchModifyRef" @refresh="handleSearch"/>
    <!-- 库存设置 -->
    <GoodsStoreForm ref="goodsStoreRef" @refresh="handleSearch"/>
  </div>
</template>

<script lang="tsx" setup>
import { computed, h, onActivated, onBeforeMount, reactive, ref } from 'vue';
import { QueryForm, QueryFormItem } from '@/components/query-form';
import useLoading from '@/hooks/use-loading';
import TableColumn, { TableColumnData } from '@/components/table-column/index.vue';
import TableToolbar from '@/components/table-toolbar/index.vue';
import useTableSelection from '@/hooks/use-table-selection';
import { ElLoading, ElMessage, ElMessageBox, ElNotification, TableInstance, TabsPaneContext } from 'element-plus';
import useTable from '@/hooks/use-table.ts';
import { hasPermission } from '@/utils/permission.ts';
import { computedOperateWidth, downloadFile, pickerShortcuts, toDecimal, toPercent } from '@/utils';
import { QueryFormItemRule } from '@/components/query-form/constants.ts';
import { goodsCategoryTreeList, goodsDelete, goodsList, goodsRestore, goodsSaleStatusUpdate, goodsTabHeader, goodsUpdateOrderNum, goodsUpdateSalesCount, shopSimpleList, TabHeaderData } from '@/api/api-shop.ts';
import { DictTag } from '@/components/dict-tag';
import { MultipleSelect, MultipleTag } from '@/components/other';
import { goodsMarkFlagOptions } from '@/utils/global-dict.ts';
import { useRouter } from 'vue-router';
import GoodsBatchModify from './components/goods-batch-modify.vue';
import GoodsStoreForm from './components/goods-store-form.vue';
import { TreeSelect } from '@/components/tree-select';
import { BaseCategory, BaseShopData } from '@/api/common.ts';
import { download } from '@/utils/axios/axios-service.ts';

defineOptions({name: 'goods-list'});

// 查询
const queryFormData = reactive({
  id: undefined,
  name: undefined,
  type: undefined,
  status: undefined,
  cate_id: undefined,
  shop_id: undefined,
  mark_flag: undefined,
  tab_type: undefined,
  // 时间范围 格式 2023-01-01~2023-01-31
  date: undefined,
});
const queryFormRef = ref<InstanceType<typeof QueryForm>>();
const queryFormItems = ref<QueryFormItemRule[]>([
  {type: 'input', prop: 'id', label: '商品编号', placeholder: '请输入商品编号', clearable: true,},
  {type: 'input', prop: 'name', label: '商品名称', placeholder: '请输入商品名称', clearable: true,},
  {type: 'dict-select', prop: 'type', label: '商品类型', placeholder: '请选择商品类型', dictType: 'shop_goods_type', clearable: true,},
  {type: 'dict-select', prop: 'type', label: '商品状态', placeholder: '请选择商品状态', dictType: 'shop_goods_status', clearable: true,},
]);
const pickerDate = ref([]);
const markFlagList = ref<Number[]>([]);
const markFlagOptions = reactive(goodsMarkFlagOptions);

// 列表数据
const tableRef = ref<TableInstance>();
const tableData = ref<any[]>([]);
const totalCount = ref(0);

// 操作区域宽度计算
const operateWidth = computed(() => {
  let count = 0
  if (hasPermission('shop:goods:info')) count += 1
  if (hasPermission('shop:goods:update')) count += 2
  return computedOperateWidth(count);
});

// 列设置
const columns = ref<TableColumnData[]>([
  {type: 'selection', width: 45, hidden: !hasPermission('shop:goods:batch_update')},
  {prop: 'id', label: '商品ID', width: 105, align: 'center', sortable: 'custom'},
  {prop: 'cover_url', label: '商品图', width: 88, align: 'center', showOverflowTooltip: false},
  {prop: 'name', label: '商品名称', width: 280, align: 'left', headerAlign: 'center', sortable: 'custom', showOverflowTooltip: false},
  {prop: 'status', label: '状态', width: 120, align: 'center', sortable: 'custom'},
  {prop: 'type', label: '类型', width: 120, align: 'center', sortable: 'custom'},
  {prop: 'price', label: '商品售价', minWidth: 110, align: 'right', headerAlign: 'center', sortable: 'custom', render: (scope, val) => <span>{toDecimal(val, 2) || '-'}</span>},
  {prop: 'price_cost', label: '供货价格', minWidth: 110, align: 'right', headerAlign: 'center', sortable: 'custom', render: (scope, val) => <span>{toDecimal(val, 2) || '-'}</span>},
  {prop: 'store_count', label: '库存', width: 110, align: 'center', sortable: 'custom'},
  {prop: 'sales_count', label: '销量', width: 110, align: 'center', sortable: 'custom'},
  {prop: 'subsidy_ratio', label: '补贴比例', minWidth: 135, align: 'right', headerAlign: 'center', sortable: 'custom', render: (scope, val) => <span>{val ? toPercent(val, 2) : '-'}</span>},
  {prop: 'rebate_ratio', label: '返利比例', minWidth: 135, align: 'right', headerAlign: 'center', sortable: 'custom', render: (scope, val) => <span>{val ? toPercent(val, 2) : '-'}</span>},
  {prop: 'promotion_ratio', label: '推广奖金', minWidth: 135, align: 'right', headerAlign: 'center', sortable: 'custom', render: (scope, val) => <span>{val ? toPercent(val, 2) : '-'}</span>},
  {prop: 'service_fee_ratio', label: '联盟服务费', minWidth: 135, align: 'right', headerAlign: 'center', sortable: 'custom', render: (scope, val) => <span>{val ? toPercent(val, 2) : '-'}</span>},
  {prop: 'mark_flag', label: '标签', width: 245, align: 'center', sortable: 'custom', showOverflowTooltip: false},
  {prop: 'order_num', label: '排序值', width: 110, align: 'center', sortable: 'custom'},
  {prop: 'create_time', label: '创建时间', width: 180, align: 'center', sortable: 'custom', render: (scope, val) => <span>{val || '-'}</span>},
  {prop: 'update_time', label: '更新时间', width: 180, align: 'center', sortable: 'custom', render: (scope, val) => <span>{val || '-'}</span>},
]);

onBeforeMount(() => {
  if (operateWidth.value > 0) {
    columns.value.push({prop: 'operations', label: '操作', fixed: 'right', width: operateWidth.value, align: 'left', headerAlign: 'center', showOverflowTooltip: false},)
  }
  initTabHeaderData();
  initShopData();
  initCateData();
});

onActivated(() => {
  if (history.state.params && parseInt(history.state.params.refresh || '0') > 0) {
    handleSearch();
  }
});

const [loading, setLoading] = useLoading(false);
const {tableMethods, tableState} = useTable(() => fetchDataList(), queryFormRef, true, true);
const {size, stripe, showQueryForm, pageQuery, pageSizes} = tableState;
const {handleSizeChange, handleCurrentChange, handleSortChange, handleResetForm} = tableMethods;
const {handleSelectChange, handleSelectAll, multipleSelection, clearSelection} = useTableSelection(tableData, tableRef);

// 数据查询
const fetchDataList = async () => {
  setLoading(true);
  try {
    handleOtherQueryParams();
    // 查询数据
    const {data} = await goodsList({
      page_num: pageQuery.pageNum,
      page_size: pageQuery.pageSize,
      order_mode: pageQuery.orderMode,
      order_column: pageQuery.orderColumn,
      ...queryFormData,
    });
    // 结果转换
    tableData.value = data.list;
    totalCount.value = data.pages.total_count;
  } catch (err) {
  } finally {
    setLoading(false);
  }
};

// 刷新数据
const handleSearch = () => {
  initTabHeaderData();
  clearSelection();
  fetchDataList();
};

const handleResetQuery = () => {
  clearSelection();
  handleResetQueryForm();
  initTabHeaderData();
};

// 重置查询条件
const handleResetQueryForm = () => {
  pickerDate.value = [];
  markFlagList.value = [];
  tabActive.value = 0;
  cateName.value = '';
  clearSelection();
  handleResetForm();
};

// 处理其他查询条件
const handleOtherQueryParams = () => {
  // 时间范围参数
  // @ts-ignore
  queryFormData.date = pickerDate.value && pickerDate.value.length == 2 ? pickerDate.value[0] + '~' + pickerDate.value[1] : undefined

  // 特殊状态标识参数
  let markFlag = 0
  // @ts-ignore
  markFlagList.value.forEach(it => markFlag |= it)
  // @ts-ignore
  queryFormData.mark_flag = markFlag > 0 ? markFlag : undefined

  // @ts-ignore
  queryFormData.tab_type = tabActive.value
  if (tabActive.value) {
    queryFormData.status = undefined
  }
}

/** 初始化商家列表 */
const shopList = ref<BaseShopData[]>([]);
const initShopData = async () => {
  shopList.value = [];
  const {data} = await shopSimpleList({type: 10});
  shopList.value = data;
};

/** 初始化分类数据 */
const cateName = ref('');
const cateTreeData = ref<BaseCategory[]>([]);
const cateTreeRef = ref();
const initCateData = async () => {
  cateTreeData.value = [];
  const {data} = await goodsCategoryTreeList();
  cateTreeData.value = data;
};

/** 处理分类选中 */
const handleSelectCate = (item?: any) => {
  queryFormData.cate_id = item
};

/** 添加/修改操作 */
const router = useRouter();
const handleFormShow = (row: any, mode: number) => {
  let goodsId = row ? row.id : 0
  if (mode === 0) { // 查看
    router.push({path: '/shop/goods/info/' + goodsId})
  } else if (mode === 1) { // 新增
    router.push({path: '/shop/goods/create/' + goodsId})
  } else if (mode === 2) { // 编辑
    if (row.status === 1 || row.status === 2) {
      ElNotification({title: '提示', message: '上架或审核中的商品不能编辑', type: 'warning', duration: 2000})
      return
    }
    router.push({path: '/shop/goods/update/' + goodsId})
  } else if (mode === 3) { // 审核
    router.push({path: '/shop/goods/audit/' + goodsId})
  }
};

/** 商品上下架操作 */
const handleUpdateSaleStatus = (row: any, on: boolean) => {
  const loading = ElLoading.service({
    lock: true,
    text: '正在提交中...',
    background: 'rgba(0, 0, 0, 0.2)'
  })
  let params = {id: row.id, status: on ? 100 : 110};
  goodsSaleStatusUpdate(params).then(response => {
    // 提示信息
    ElNotification({title: '成功', message: '操作完成', type: 'success', duration: 2000})
    // 刷新列表数据
    handleSearch();
  }).finally(() => loading.close())
};

/** Tab数据 */
const tabActive = ref(0);
const tabHeaderList = ref<TabHeaderData[]>([]);
const initTabHeaderData = async () => {
  handleOtherQueryParams();
  const {data} = await goodsTabHeader(queryFormData);
  tabHeaderList.value = data;
};

/** Tab 改变时触发 */
const handleTabChange = (tab: TabsPaneContext, event: Event) => {
  fetchDataList();
};

/** 批量修改操作 */
const batchModifyRef = ref<any>()
const handleShowBatchModify = () => {
  const itemIds = multipleSelection.value.map((item) => item.id);
  batchModifyRef.value?.open(itemIds, tabActive.value)
};

/** 商品删除操作 */
const handleGoodsDelete = (row: any) => {
  // 弹窗提示
  ElMessageBox.confirm(h('p', null, ['您确定将商品 ', h('span', {style: 'font-weight: bold;'}, row.name), ` 进行 `, h('span', {style: 'font-weight: bold;'}, '删除'), ` 操作吗 ？`,]), '提示', {
    type: 'warning',
    closeOnClickModal: false,
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    inputPlaceholder: '请输入操作原因',
  }).then(() => {
    const loading = ElLoading.service({
      lock: true,
      text: '正在提交中...',
      background: 'rgba(0, 0, 0, 0.2)'
    })
    // 提交数据
    goodsDelete(row.id).then(response => {
      // 提示信息
      ElNotification({title: '成功', message: '操作完成', type: 'success', duration: 2000})
      // 刷新列表数据
      handleSearch();
    }).finally(() => loading.close())
  }).catch(() => {

  });
};

/** 商品恢复 */
const handleGoodsRestore = (row: any) => {
  // 弹窗提示
  ElMessageBox.confirm(h('p', null, ['您确定将商品 ', h('span', {style: 'font-weight: bold;'}, row.name), ` 进行 `, h('span', {style: 'font-weight: bold;'}, '恢复'), ` 操作吗 ？`,]), '提示', {
    type: 'warning',
    closeOnClickModal: false,
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    inputPlaceholder: '请输入操作原因',
  }).then(() => {
    const loading = ElLoading.service({
      lock: true,
      text: '正在提交中...',
      background: 'rgba(0, 0, 0, 0.2)'
    })
    // 提交数据
    goodsRestore(row.id).then(response => {
      // 提示信息
      ElNotification({title: '成功', message: '操作完成', type: 'success', duration: 2000})
      // 刷新列表数据
      handleSearch();
    }).finally(() => loading.close())
  }).catch(() => {

  });
};

/** 商品仓库设置 */
const goodsStoreRef = ref();
const showGoodsStoreForm = (id: number) => {
  goodsStoreRef.value?.open(id);
};

/** 排序值修改 */
const handleUpdateOrderNum = (row: any) => {
  if (row == null || row.id <= 0) return
  if (!hasPermission('shop:goods:update')) return

  ElMessageBox.prompt(h('p', null, [
    '修改 ',
    h('span', {style: 'font-weight: bold;'}, row.name),
    ` 的 `,
    h('span', {style: 'font-weight: bold;'}, '排序值'),
    ` 操作`,
    <br/>, '提示：排序值越大越靠前'
  ]), '提示', {
    type: 'warning',
    closeOnClickModal: false,
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    inputPlaceholder: '请输入排序值',
    inputPattern: /^[0-9]*$/,
  }).then(({value}) => {
    let newValue = parseInt(value) || 0
    if (newValue < 0) {
      ElMessage.error('请输入排序值');
      return
    }
    const loading = ElLoading.service({
      lock: true,
      text: '正在提交中...',
      background: 'rgba(0, 0, 0, 0.2)'
    });
    goodsUpdateOrderNum({id: row.id, count: newValue}).then(response => {
      // 提示信息
      ElNotification({title: '成功', message: '操作完成', type: 'success', duration: 2000})
      // 刷新列表数据
      handleSearch();
    }).finally(() => loading.close())
  }).catch(() => {

  });
};

/** 商品销量修改 */
const handleUpdateSalesCount = (row: any) => {
  if (row == null || row.id <= 0) return
  if (!hasPermission('shop:goods:update')) return

  ElMessageBox.prompt(h('p', null, [
    '修改 ',
    h('span', {style: 'font-weight: bold;'}, row.name),
    ` 的 `,
    h('span', {style: 'font-weight: bold;'}, '销量'),
    ` 操作`,
  ]), '提示', {
    type: 'warning',
    closeOnClickModal: false,
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    inputPlaceholder: '请输入销量',
    inputPattern: /^[0-9]*$/,
  }).then(({value}) => {
    let newValue = parseInt(value) || 0
    if (newValue < 0) {
      ElMessage.error('请输入销量');
      return
    }
    const loading = ElLoading.service({
      lock: true,
      text: '正在提交中...',
      background: 'rgba(0, 0, 0, 0.2)'
    });
    goodsUpdateSalesCount({id: row.id, count: newValue}).then(response => {
      // 提示信息
      ElNotification({title: '成功', message: '操作完成', type: 'success', duration: 2000})
      // 刷新列表数据
      handleSearch();
    }).finally(() => loading.close())
  }).catch(() => {

  });
};

/** 导出数据 */
const handleDownloadExport = () => {
  ElMessageBox.confirm(h('p', null, ['是否确认进行 ', h('span', {style: 'font-weight: bold;'}, '导出商品数据'), ` 操作吗？ 注：导出数据按查询条件进行筛选导出`,]), '提示', {
    type: 'warning',
    closeOnClickModal: false,
    confirmButtonText: '确定',
    cancelButtonText: '取消',
  }).then(() => {
    const loading = ElLoading.service({
      lock: true,
      text: '正在导出数据中...',
      background: 'rgba(0, 0, 0, 0.2)'
    })
    // 时间范围参数
    // @ts-ignore
    queryFormData.date = pickerDate.value && pickerDate.value.length == 2 ? pickerDate.value[0] + '~' + pickerDate.value[1] : undefined;
    // 调用函数
    download('/shop/goods/download_excel', queryFormData).then(result => {
      downloadFile(result, `商品数据`, 'xlsx')
    }).finally(() => loading.close())
  }).catch(() => {

  });
};

</script>

<style lang="scss" scoped>
:deep(.table-wrapper) {
  .el-table__row .el-table__cell {
    vertical-align: top;
  }

  .mark_flag {
    text-align: left;

    .el-tag {
      margin-right: 5px;
      margin-bottom: 5px;
    }

    .el-tag + .el-tag {
      margin-left: initial;
    }
  }
}

.sku-info-box {
  :deep() {
    .el-image {
      width: 42px;
      height: 42px;
    }

    .el-image__error {
      font-size: 9px;
    }
  }

  .sku-info-right {
    display: flex;
    flex-direction: column;
    justify-content: center;

    .sku-name {
      font-size: 12px;
      line-height: 14px;
      overflow: hidden;
      text-overflow: ellipsis;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
    }
  }
}
</style>
